class STECardElement extends HTMLElement {
    constructor() {
        super();
        this.defined = false;
    }
    connectedCallback() {
        if (this.defined || !this.isConnected) return;
        this.defined = true;
        this.addEventListener("keydown", event => {
            if (this.getAttribute("data-type") != "dialog" || event.key != "Tab") return;
            var navigable = getNavigableElements({ container: this, scope: true });
            if (!event.shiftKey) {
                if (document.activeElement != navigable[navigable.length - 1]) return;
                event.preventDefault();
                navigable[0].focus();
            } else if (document.activeElement == navigable[0]) {
                event.preventDefault();
                navigable[navigable.length - 1].focus();
            }
        });
        this.type = this.getAttribute("data-type");
        this.header = this.querySelector(".header");
        this.back = document.createElement("button");
        this.back.classList.add("card-back");
        this.back.innerHTML = `<svg><use href="#back_icon"/></svg>`;
        this.back.addEventListener("click", () => document.querySelector(`#${this.header.getAttribute("data-card-parent")}`).open(this));
        this.heading = this.header.querySelector(".heading");
        this.controls = document.createElement("div");
        this.controls.classList.add("card-controls");
        this.controls.minimize = document.createElement("button");
        this.controls.minimize.classList.add("control");
        this.controls.minimize.setAttribute("data-control", "minimize");
        this.controls.minimize.innerHTML = `<svg><use href="#minimize_icon"/></svg>`;
        this.controls.minimize.addEventListener("keydown", event => {
            if (event.key != "Enter") return;
            event.preventDefault();
            if (event.repeat) return;
            this.controls.minimize.click();
        });
        this.controls.minimize.addEventListener("click", () => this.minimize());
        this.controls.close = document.createElement("button");
        this.controls.close.classList.add("control");
        this.controls.close.setAttribute("data-control", "close");
        this.controls.close.innerHTML = `<svg><use href="#close_icon"/></svg>`;
        this.controls.close.addEventListener("click", () => this.close());
        this.header.insertBefore(this.back, this.heading);
        this.controls.appendChild(this.controls.minimize);
        this.controls.appendChild(this.controls.close);
        this.header.appendChild(this.controls);
        if (Editor.environment().macOS_device) {
            this.controls.insertBefore(this.controls.close, this.controls.minimize);
            this.header.insertBefore(this.controls, this.header.firstChild);
        }
    }
    open(previous) {
        if (this.matches(".active") && !this.hasAttribute("data-alert-timeout")) return this.close();
        if (this.type != "alert") {
            document.querySelectorAll(`.card.active`).forEach(card => {
                if (card.type != "dialog" && card.type != this.type) return;
                card.close();
                if (!card.matches(".minimize")) return;
                var transitionDuration = parseInt(getElementStyle({ element: card, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000);
                window.setTimeout(() => card.minimize(), transitionDuration);
            });
        }
        this.classList.add("active");
        if (this.type == "widget" && card_backdrop.matches(".active")) card_backdrop.classList.remove("active");
        if (this.type == "alert") {
            var timeoutIdentifier = Math.random().toString();
            this.setAttribute("data-alert-timeout", timeoutIdentifier);
            window.setTimeout(() => {
                if (this.getAttribute("data-alert-timeout") != timeoutIdentifier) return;
                this.removeAttribute("data-alert-timeout");
                this.close();
            }, 4000);
        }
        if (this.type == "dialog") {
            document.body.addEventListener("keydown", catchCardNavigation);
            card_backdrop.classList.add("active");
            if (!Editor.active_dialog && !Editor.dialog_previous) {
                Editor.dialog_previous = document.activeElement;
            }
            document.querySelectorAll("menu-drop[data-open]").forEach(menu => menu.close());
            var transitionDuration = parseInt(getElementStyle({ element: this, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 500);
            window.setTimeout(() => {
                document.activeElement.blur();
                if (previous) this.querySelector(`[data-card-previous="${previous.id}"]`).focus();
            }, transitionDuration);
            Editor.active_dialog = this;
        }
        if (this.type == "widget") Editor.active_widget = this;
    }
    minimize() {
        var icon = this.controls.minimize.querySelector("svg use"), main = this.querySelector(".main"), changeIdentifier = Math.random().toString();
        this.setAttribute("data-minimize-change", changeIdentifier);
        workspace_tabs.setAttribute("data-minimize-change", changeIdentifier);
        var transitionDuration = parseInt(getElementStyle({ element: this, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000);
        if (!this.matches(".minimize")) {
            this.classList.add("minimize");
            this.style.setProperty("--card-minimize-width", `${this.controls.minimize.querySelector("svg").clientWidth + parseInt(getElementStyle({ element: this.controls.minimize, property: "--control-padding" }), 10) * 2}px`);
            this.style.setProperty("--card-main-width", `${main.clientWidth}px`);
            this.style.setProperty("--card-main-height", `${main.clientHeight}px`);
            icon.setAttribute("href", "#arrow_icon");
            window.setTimeout(() => {
                workspace_tabs.style.setProperty("--minimize-tab-width", getElementStyle({ element: this, property: "width" }));
                setEditorTabsVisibility();
            }, transitionDuration);
            if (this.contains(document.activeElement) && document.activeElement != this.controls.minimize) this.controls.minimize.focus();
        } else {
            this.classList.remove("minimize");
            window.setTimeout(() => {
                if (this.getAttribute("data-minimize-change") == changeIdentifier) this.style.removeProperty("--card-minimize-width");
            }, transitionDuration);
            this.style.removeProperty("--card-main-width");
            this.style.removeProperty("--card-main-height");
            icon.setAttribute("href", "#minimize_icon");
            workspace_tabs.style.removeProperty("--minimize-tab-width");
        }
        window.setTimeout(() => {
            if (this.getAttribute("data-minimize-change") == changeIdentifier) this.removeAttribute("data-minimize-change");
            if (workspace_tabs.getAttribute("data-minimize-change") == changeIdentifier) workspace_tabs.removeAttribute("data-minimize-change");
        }, transitionDuration);
    }
    close() {
        this.classList.remove("active");
        if (this.matches(".minimize")) {
            var transitionDuration = parseInt(getElementStyle({ element: this, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000);
            window.setTimeout(() => this.minimize(), transitionDuration);
        }
        if (this.type == "dialog") {
            document.body.removeEventListener("keydown", catchCardNavigation);
            card_backdrop.classList.remove("active");
            Editor.active_dialog = null;
            if (Editor.dialog_previous) {
                var hidden = (getElementStyle({ element: Editor.dialog_previous, property: "visibility" }) == "hidden");
                (!workspace_editors.contains(Editor.dialog_previous) && !hidden) ? Editor.dialog_previous.focus({ preventScroll: true }) : Editor.query().container.focus({ preventScroll: true });
                Editor.dialog_previous = null;
            }
        }
        if (this.type == "widget") Editor.active_widget = null;
    }
}
function catchCardNavigation() {
    if (!Editor.active_dialog || event.key != "Tab" || document.activeElement != document.body) return;
    var navigable = getNavigableElements({ container: Editor.active_dialog, scope: true });
    event.preventDefault();
    navigable[((!event.shiftKey) ? 0 : navigable.length - 1)].focus();
}
window.customElements.define("ste-card", STECardElement);

document.querySelectorAll("img").forEach(image => image.draggable = false);
document.querySelectorAll("num-text").forEach(textarea => applyEditingBehavior({ element: textarea }));
document.querySelectorAll("input:is([type='text'],[type='url'])").forEach(input => applyEditingBehavior({ element: input }));
document.querySelectorAll(".checkbox").forEach(checkbox => {
    var input = checkbox.querySelector("input[type='checkbox']");
    checkbox.addEventListener("click", () => input.click());
    checkbox.addEventListener("keydown", event => {
        if (!event.repeat && event.key == "Enter") input.click();
    });
    checkbox.addEventListener("keyup", event => {
        if (event.key == " ") input.click();
    });
    checkbox.tabIndex = 0;
    input.addEventListener("click", event => event.stopPropagation());
});
document.querySelectorAll("header .app-omnibox .option").forEach(option => {
    option.tabIndex = -1;
    option.addEventListener("mousedown", event => event.preventDefault());
});
window.Tools = {
    replaceText: {
        replace: () => {
            var { container: editor } = Editor.query();
            if (!editor) return;
            var replaced = editor.value.split(replacer_find.value).join(replacer_replace.value);
            if (replaced != editor.value) editor.value = replaced;
        },
        flip: () => [replacer_find.value, replacer_replace.value] = [replacer_replace.value, replacer_find.value],
        clear: () => [replacer_find.value, replacer_replace.value] = ""
    },
    jsonFormatter: {
        format: (spacing = "  ") => {
            try {
                var formatted = JSON.stringify(JSON.parse(formatter_input.value), null, spacing);
                if (formatted != formatter_input.value) formatter_input.value = formatted;
            } catch (error) {/* Make matching for "position" optional, as Safari doesn't give JSON parsing error data, it only says that an error occurred. */
                var message = error.toString().match(/^(.+?)position /)[0],
                    errorIndex = error.toString().match(/position (\d+)/)[1],

                    errorLine,
                    errorLineIndex = (() => {
                        var lineIndexes = indexi("\n", formatter_input.value);
                        errorLine = formatter_input.value.substring(0, errorIndex).split("\n").length - 1;
                        return lineIndexes[errorLine - 1] || 1;
                    })(),
                    errorPosition = errorIndex - errorLineIndex + 1;

                alert(`Could not parse JSON, an error occurred.\n${message}line ${errorLine + 1} position ${errorPosition}`);
            }


            function indexi(char, str) {
                var list = [], i = -1;
                while ((i = str.indexOf(char, i + 1)) >= 0) list.push(i + 1);
                return list;
            }


        },
        collapse: () => {
            Tools.jsonFormatter.format("");
        },
        clear: () => formatter_input.value = ""
    },
    uriEncoder: {
        encode: () => {
            var encodingType = (!encoder_type.checked) ? encodeURI : encodeURIComponent;
            encoder_input.value = encodingType(encoder_input.value);
        },
        decode: () => {
            var decodingType = (!encoder_type.checked) ? decodeURI : decodeURIComponent;
            encoder_input.value = decodingType(encoder_input.value);
        },
        clear: () => encoder_input.value = ""
    },
    uuidGenerator: (() => {
        var lut = [];
        for (var i = 0; i < 256; i++) lut[i] = ((i < 16) ? "0" : "") + i.toString(16);
        return {
            generate: () => {
                var d0 = (Math.random() * 0xffffffff) | 0, d1 = (Math.random() * 0xffffffff) | 0, d2 = (Math.random() * 0xffffffff) | 0, d3 = (Math.random() * 0xffffffff) | 0;
                return `${lut[d0 & 0xff]}${lut[(d0 >> 8) & 0xff]}${lut[(d0 >> 16) & 0xff]}${lut[(d0 >> 24) & 0xff]}-${lut[d1 & 0xff]}${lut[(d1 >> 8) & 0xff]}-${lut[((d1 >> 16) & 0x0f) | 0x40]}${lut[(d1 >> 24) & 0xff]}-${lut[(d2 & 0x3f) | 0x80]}${lut[(d2 >> 8) & 0xff]}-${lut[(d2 >> 16) & 0xff]}${lut[(d2 >> 24) & 0xff]}${lut[d3 & 0xff]}${lut[(d3 >> 8) & 0xff]}${lut[(d3 >> 16) & 0xff]}${lut[(d3 >> 24) & 0xff]}`;
            }
        };
    })(),
    insertTemplate: ({ type } = {}) => {
        var template, editor = Editor.query(), name;
        if (type == "html") {
            var language = navigator.language;
            if (language.includes("-")) language = language.replace(/[^-]+$/g, code => code.toUpperCase());
            name = "index.html";
            template = decodeURI(`%3C!DOCTYPE%20html%3E%0A%3Chtml%20lang=%22${language}%22%3E%0A%0A%3Chead%3E%0A%0A%3Ctitle%3E%3C/title%3E%0A%3Cmeta%20charset=%22UTF-8%22%3E%0A%3Cmeta%20name=%22viewport%22%20content=%22width=device-width,%20initial-scale=1%22%3E%0A%0A%3Cstyle%3E%0A%20%20*,%20*::before,%20*::after%20%7B%0A%20%20%20%20box-sizing:%20border-box;%0A%20%20%7D%0A%20%20body%20%7B%0A%20%20%20%20font-family:%20sans-serif;%0A%20%20%7D%0A%3C/style%3E%0A%0A%3C/head%3E%0A%0A%3Cbody%3E%0A%0A%3Cscript%3E%0A%3C/script%3E%0A%0A%3C/body%3E%0A%0A%3C/html%3E`);
        }
        if (type == "pack-manifest-bedrock") {
            name = "manifest.json";
            template = decodeURI(`%7B%0A%20%20%22format_version%22:%202,%0A%0A%20%20%22header%22:%20%7B%0A%20%20%20%20%22name%22:%20%22Pack%20Manifest%20Template%20-%20Bedrock%20Edition%22,%0A%20%20%20%20%22description%22:%20%22Your%20resource%20pack%20description%22,%0A%20%20%20%20%22uuid%22:%20%22${Tools.uuidGenerator.generate()}%22,%0A%20%20%20%20%22version%22:%20%5B%201,%200,%200%20%5D,%0A%20%20%20%20%22min_engine_version%22:%20%5B%201,%2013,%200%20%5D%0A%20%20%7D,%0A%20%20%22modules%22:%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22description%22:%20%22Your%20resource%20pack%20description%22,%0A%20%20%20%20%20%20%22type%22:%20%22resources%22,%0A%20%20%20%20%20%20%22uuid%22:%20%22${Tools.uuidGenerator.generate()}%22,%0A%20%20%20%20%20%20%22version%22:%20%5B%201,%200,%200%20%5D%0A%20%20%20%20%7D%0A%20%20%5D,%0A%20%20%22metadata%22:%20%7B%0A%20%20%20%20%22authors%22:%20%5B%0A%20%20%20%20%20%20%22Add%20author%20names%20here%20(optional,%20'metadata'%20can%20be%20removed%20altogether)%22%0A%20%20%20%20%5D%0A%20%20%7D%0A%7D`);
        }
        if (!template) return;
        createEditor({ name, value: template });
        if (Editor.view() == "preview") setView({ type: "split" });
    }
};
window.addEventListener("load", () => {
    if (Editor.environment().file_protocol) return;
    if (window.location.href.includes("index.html")) history.pushState(null, "", window.location.href.replace(/index.html/, ""));
    if (!("serviceWorker" in navigator) || !Editor.appearance().parent_window) return;
    navigator.serviceWorker.register("service-worker.js").then(() => {
        if ((navigator.serviceWorker.controller) ? (navigator.serviceWorker.controller.state == "activated") : false) activateManifest();
        navigator.serviceWorker.addEventListener("message", event => {
            if (event.data.action == "service-worker-activated") activateManifest();
            if (event.data.action == "clear-site-caches-complete") cleared_cache_card.open();
            if (event.data.action == "share-target") {
                event.data.files.forEach(file => {
                    var reader = new FileReader();
                    reader.readAsText(file, "UTF-8");
                    reader.addEventListener("loadend", () => createEditor({ name: file.name, value: reader.result }));
                });
            }
        });
        document.documentElement.classList.add("service-worker-activated");
        if (queryParameters.get("share-target")) {
            navigator.serviceWorker.controller.postMessage({ action: "share-target" });
            removeQueryParameters(["share-target"]);
        }
    });
    function activateManifest() {
        document.querySelector("link[rel='manifest']").href = "manifest.webmanifest";
    }
});
window.addEventListener("beforeinstallprompt", event => {
    event.preventDefault();
    Editor.install_prompt = event;
    document.documentElement.classList.add("install-prompt-available");
    theme_button.childNodes[0].textContent = "Theme";
});
window.addEventListener("beforeunload", event => {
    if (Editor.unsaved_work()) return;
    event.preventDefault();
    event.returnValue = "";
});
window.addEventListener("unload", () => Editor.child_windows.forEach(window => window.close()));
window.addEventListener("resize", event => {
    Editor.appearance().refresh_window_controls_overlay();
    Editor.appearance().refresh_device_pixel_ratio();
    if (Editor.view() != "preview") setEditorTabsVisibility();
    if (Editor.view() == "split" && document.body.hasAttribute("data-scaling-active")) setView({ type: "split" });
});
window.addEventListener("blur", () => {
    if (Editor.appearance().parent_window) document.querySelectorAll("menu-drop[data-open]").forEach(menu => menu.close());
});
document.body.addEventListener("keydown", event => {
    var pressed = key => (event.key.toLowerCase() == key.toLowerCase()), control = (event.ctrlKey && !Editor.environment().apple_device), command = (event.metaKey && Editor.environment().apple_device), shift = (event.shiftKey || ((event.key.toUpperCase() == event.key) && (event.key + event.key == event.key * 2))), controlShift = (control && shift), shiftCommand = (shift && command), controlCommand = (event.ctrlKey && command);
    if (pressed("Escape")) {
        event.preventDefault();
        if (event.repeat) return;
        if (Editor.active_dialog && !document.activeElement.matches("menu-drop[data-open]")) Editor.active_dialog.close();
    }
    if (((control || command) && !shift && pressed("n")) || ((controlShift || shiftCommand) && pressed("x"))) {
        event.preventDefault();
        if (event.repeat) return;
        createEditor({ auto_replace: false });
    }
    if (((control || command) && pressed("w")) || ((controlShift || shiftCommand) && pressed("d"))) {
        if (shift && pressed("w")) return window.close();
        event.preventDefault();
        if (event.repeat) return;
        /* Future feature: If an editor tab is focused, close that editor instead of only the active editor */
        closeEditor();
    }
    if (((controlShift || (event.ctrlKey && shift && !command && Editor.environment().apple_device)) && pressed("Tab")) || ((controlShift || controlCommand) && (pressed("[") || pressed("{")))) {
        event.preventDefault();
        if (event.repeat) return;
        openEditor({ identifier: getPreviousEditor() });
    }
    if (((control || (event.ctrlKey && !command && Editor.environment().apple_device)) && !shift && pressed("Tab")) || ((controlShift || controlCommand) && (pressed("]") || pressed("}")))) {
        event.preventDefault();
        if (event.repeat) return;
        openEditor({ identifier: getNextEditor() });
    }
    if (((controlShift || shiftCommand) && pressed("n")) || ((controlShift || shiftCommand) && pressed("c"))) {
        event.preventDefault();
        if (event.repeat) return;
        createWindow();
    }
    if ((control || command) && !shift && pressed("o")) {
        event.preventDefault();
        if (event.repeat) return;
        openFiles();
    }
    if ((controlShift || shiftCommand) && pressed("r")) {
        event.preventDefault();
        if (event.repeat) return;
        renameEditor();
    }
    if ((control || command) && !shift && pressed("s")) {
        event.preventDefault();
        if (event.repeat) return;
        saveFile();
    }
    if ((controlShift || controlCommand) && (pressed("1") || pressed("!"))) {
        event.preventDefault();
        if (event.repeat) return;
        setView({ type: "code" });
    }
    if ((controlShift || controlCommand) && (pressed("2") || pressed("@"))) {
        event.preventDefault();
        if (event.repeat) return;
        setView({ type: "split" });
    }
    if ((controlShift || controlCommand) && (pressed("3") || pressed("#"))) {
        event.preventDefault();
        if (event.repeat) return;
        setView({ type: "preview" });
    }
    if ((controlShift || controlCommand) && (pressed("4") || pressed("$"))) {
        event.preventDefault();
        if (event.repeat) return;
        setOrientation();
    }
    if ((controlShift || controlCommand) && (pressed("5") || pressed("%"))) {
        event.preventDefault();
        if (event.repeat) return;
        createDisplay();
    }
    if ((controlShift || shiftCommand) && pressed("Enter")) {
        event.preventDefault();
        if (event.repeat) return;
        refreshPreview({ force: true });
    }
    if ((controlShift || shiftCommand) && pressed("B")) {
        event.preventDefault();
        if (event.repeat) return;
        preview_base_card.open();
    }
    if ((controlShift || shiftCommand) && pressed("f")) {
        event.preventDefault();
        if (event.repeat) return;
        replace_text_card.open();
    }/*
    if ((controlShift || shiftCommand) && pressed("k")){
      event.preventDefault();
      if (event.repeat) return;
      color_picker_card.open();
    }*/
    if ((controlShift || shiftCommand) && pressed("g")) {
        event.preventDefault();
        if (event.repeat) return;
        json_formatter_card.open();
    }
    if ((controlShift || shiftCommand) && pressed("y")) {
        event.preventDefault();
        if (event.repeat) return;
        uri_encoder_card.open();
    }
    if ((controlShift || shiftCommand) && pressed("o")) {
        event.preventDefault();
        if (event.repeat) return;
        uuid_generator_card.open();
    }
    if ((controlShift || shiftCommand) && pressed("h")) {
        event.preventDefault();
        if (event.repeat) return;
        Tools.insertTemplate({ type: "html" });
    }
    if ((controlShift || shiftCommand) && pressed("m")) {
        event.preventDefault();
        if (event.repeat || !Editor.active_widget) return;
        if (Editor.active_widget) Editor.active_widget.minimize();
    }
    if ((control || command) && (pressed(",") || pressed("<"))) {
        event.preventDefault();
        if (event.repeat) return;
        settings_card.open();
    }
}, { capture: true });
document.body.addEventListener("mousedown", event => {
    if (event.button != 2) return;
    event.preventDefault();
    event.stopPropagation();
});
document.body.addEventListener("contextmenu", event => event.preventDefault());
document.body.addEventListener("dragover", event => {
    event.preventDefault();
    event.dataTransfer.dropEffect = (event.target.matches("menu-drop, header, .card") || event.target.closest("menu-drop, header, .card")) ? "none" : "copy";
});
document.body.addEventListener("drop", event => {
    event.preventDefault();
    document.querySelectorAll("menu-drop[data-open]").forEach(menu => menu.close());
    Array.from(event.dataTransfer.items).forEach(async (item, index) => {
        if (item.kind == "file") {
            if (!Editor.support().file_system || !("getAsFileSystemHandle")) {
                var file = item.getAsFile(), reader = new FileReader();
                reader.readAsText(file, "UTF-8");
                reader.addEventListener("loadend", () => createEditor({ name: file.name, value: reader.result }));
            } else {
                var handle = await item.getAsFileSystemHandle();
                if (handle.kind != "file") return;
                var file = await handle.getFile(), identifier = createEditor({ name: await file.name, value: await file.text() });
                Editor.file_handles[identifier] = await handle;
            }
        } else if (item.kind == "string" && index == 0 && event.dataTransfer.getData("text") != "") createEditor({ value: event.dataTransfer.getData("text") });
    });
});
var toolbar = document.querySelector("header .app-menubar");
toolbar.querySelectorAll("menu-drop").forEach(menu => {
    menu.addEventListener("pointerenter", () => {
        if (event.pointerType != "mouse") return;
        if (toolbar.querySelectorAll("menu-drop:not([data-alternate])[data-open]").length == 0 || menu.matches("[data-alternate]") || menu.matches("[data-open]")) return;
        menu.opener.focus();
        toolbar.querySelectorAll("menu-drop[data-open]").forEach(menu => menu.close());
        menu.open();
    });
});
workspace_tabs.addEventListener("keydown", event => {
    if (event.key != "ArrowLeft" && event.key != "ArrowRight") return;
    if (!workspace_tabs.contains(document.activeElement)) return;
    var identifier = document.activeElement.getAttribute("data-editor-identifier"),
        previousEditor = getPreviousEditor({ identifier }),
        nextEditor = getNextEditor({ identifier });
    event.preventDefault();
    if (event.key == "ArrowLeft") Editor.query(previousEditor).tab.focus();
    if (event.key == "ArrowRight") Editor.query(nextEditor).tab.focus();
});
create_editor_button.addEventListener("keydown", event => {
    if (event.key != "Enter") return;
    if (event.repeat) event.preventDefault();
});
create_editor_button.addEventListener("mousedown", event => event.preventDefault());
create_editor_button.addEventListener("click", () => createEditor({ auto_replace: false }));
scaler.addEventListener("mousedown", event => {
    if (event.button != 0) return;
    if (Editor.view() != "split") return;
    event.preventDefault();
    document.body.setAttribute("data-scaling-change", true);
    document.addEventListener("mousemove", setScaling);
    document.addEventListener("mouseup", disableScaling);
});
scaler.addEventListener("touchstart", event => {
    if (Editor.view() != "split" || event.touches.length != 1) return;
    document.body.setAttribute("data-scaling-change", true);
    document.addEventListener("touchmove", setScaling, { passive: true });
    document.addEventListener("touchend", disableScaling, { passive: true });
}, { passive: true });
card_backdrop.addEventListener("click", () => Editor.active_dialog.close());
preview_base_input.placeholder = document.baseURI;
preview_base_input.setWidth = () => preview_base_input.style.setProperty("--input-count", preview_base_input.value.length);
preview_base_input.setValue = value => {
    preview_base_input.value = value;
    preview_base_input.setWidth();
};
preview_base_input.reset = () => {
    preview_base_input.setValue("");
    if (!Editor.settings.has("preview-base")) return;
    Editor.settings.remove("preview-base");
    refreshPreview({ force: true });
};
preview_base_input.style.setProperty("--placeholder-count", preview_base_input.placeholder.length);
preview_base_input.addEventListener("input", event => event.target.setWidth());
preview_base_input.addEventListener("change", event => {
    var empty = event.target.matches(":placeholder-shown"), valid = event.target.matches(":valid");
    if (empty || !valid) Editor.settings.remove("preview-base");
    if (!empty && valid) Editor.settings.set("preview-base", event.target.value);
    if (empty || valid) refreshPreview({ force: true });
});
generator_output.addEventListener("click", () => generator_output.select());
generator_output.addEventListener("keydown", () => generator_output.click());

window.requestAnimationFrame(() => createEditor({ auto_created: true }));
if (Editor.appearance().parent_window) {
    if (Editor.settings.get("default-orientation")) {
        var value = Editor.settings.get("default-orientation");
        window.requestAnimationFrame(() => default_orientation_setting.select(value));
        setOrientation(value);
    }
    if (Editor.settings.get("syntax-highlighting") != undefined) {
        var state = Editor.settings.get("syntax-highlighting");
        setSyntaxHighlighting(state);
        syntax_highlighting_setting.checked = state;
    }
    if (Editor.settings.get("automatic-refresh") != undefined) automatic_refresh_setting.checked = Editor.settings.get("automatic-refresh");
    if (Editor.settings.get("preview-base")) preview_base_input.setValue(Editor.settings.get("preview-base"));
    window.setTimeout(() => document.documentElement.classList.remove("startup-fade"), 50);
}
if (Editor.support().file_handling && Editor.support().file_system) {
    window.launchQueue.setConsumer(params => {
        params.files.forEach(async handle => {
            var file = await handle.getFile(), identifier = createEditor({ name: await file.name, value: await file.text() });
            Editor.file_handles[identifier] = await handle;
        });
        if (!Editor.environment().touch_device) Editor.query().container.focus({ preventScroll: true });
    });
}
var queryParameters = new URLSearchParams(window.location.search);
if (queryParameters.get("template")) {
    Tools.insertTemplate({ type: "html" });
    removeQueryParameters(["template"]);
}
if (queryParameters.get("settings")) {
    settings_card.open();
    removeQueryParameters(["settings"]);
}
function createEditor({ name = "Untitled.txt", value = "", open = true, auto_created = false, auto_replace = true } = {}) {
    var identifier = Math.random().toString(), tab = document.createElement("button"), editorName = document.createElement("span"), editorClose = document.createElement("button"), container = document.createElement("num-text"), previewOption = document.createElement("li"), focused_override, changeIdentifier = Math.random().toString();
    document.body.setAttribute("data-editor-change", changeIdentifier);
    var transitionDuration = parseInt(getElementStyle({ element: workspace_tabs, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000);
    if (!name.includes(".")) name = `${name}.txt`;
    tab.classList.add("tab");
    tab.setAttribute("data-editor-identifier", identifier);
    if (value) tab.setAttribute("data-editor-refresh", true);
    tab.addEventListener("mousedown", event => {
        if (event.button != 0 || document.activeElement.matches("[data-editor-rename]")) return;
        event.preventDefault();
        if (tab != Editor.query().tab) openEditor({ identifier });
    });
    tab.addEventListener("keydown", event => {
        if (event.key != " " && event.key != "Enter") return;
        event.preventDefault();
        if (tab != Editor.query().tab) openEditor({ identifier });
    });
    tab.addEventListener("contextmenu", event => {
        if (event.target != tab) return;
        var editorRename = tab.querySelector("[data-editor-rename]");
        if (!editorRename) {
            editorRename = document.createElement("input");
        } else return editorRename.blur();
        editorRename.type = "text";
        editorRename.placeholder = Editor.query(identifier).getName();
        editorRename.setAttribute("data-editor-rename", true);
        editorRename.tabIndex = -1;
        editorRename.style.setProperty("--editor-name-width", `${editorName.offsetWidth}px`);
        editorRename.value = Editor.query(identifier).getName();
        editorRename.addEventListener("keydown", event => {
            if (event.key == "Escape") editorRename.blur();
        });
        editorRename.addEventListener("input", () => {
            editorRename.style.width = "0px";
            editorRename.offsetWidth;
            editorRename.style.setProperty("--editor-rename-width", `${editorRename.scrollWidth + 1}px`);
            editorRename.style.removeProperty("width");
        });
        editorRename.addEventListener("change", () => {
            if (editorRename.value) renameEditor({ name: editorRename.value, identifier });
            editorRename.blur();
        });
        editorRename.addEventListener("blur", () => editorRename.remove());
        tab.insertBefore(editorRename, tab.firstChild);
        applyEditingBehavior({ element: editorRename, advanced: false });
        editorRename.focus();
        editorRename.select();
    });
    tab.addEventListener("dragover", event => {
        event.preventDefault();
        event.stopPropagation();
        event.dataTransfer.dropEffect = "copy";
        if (tab != Editor.query().tab) openEditor({ identifier });
    });
    editorName.setAttribute("data-editor-name", name);
    editorName.innerText = name;
    editorClose.classList.add("option");
    editorClose.tabIndex = -1;
    editorClose.innerHTML = "<svg><use href='#close_icon'/></svg>";
    editorClose.addEventListener("mousedown", event => {
        event.preventDefault();
        event.stopPropagation();
    });
    editorClose.addEventListener("click", event => {
        event.stopPropagation();
        closeEditor({ identifier });
    });
    container.classList.add("editor");
    container.setAttribute("data-editor-identifier", identifier);
    container.setAttribute("value", value);
    previewOption.part = "option";
    previewOption.classList.add("option");
    previewOption.setAttribute("data-editor-identifier", identifier);
    previewOption.tabIndex = -1;
    previewOption.innerText = name;
    previewOption.addEventListener("click", () => setPreviewSource({ identifier }));
    if ((Editor.active_editor) ? Editor.query().tab.hasAttribute("data-editor-auto-created") : false) {
        if (document.activeElement == Editor.query().container) focused_override = true;
        if (auto_replace) {
            closeEditor();
        } else Editor.query().tab.removeAttribute("data-editor-auto-created");
    }
    tab.appendChild(editorName);
    tab.appendChild(editorClose);
    workspace_tabs.insertBefore(tab, create_editor_button);
    workspace_editors.appendChild(container);
    container.editor.addEventListener("input", () => {
        if (tab.hasAttribute("data-editor-auto-created")) tab.removeAttribute("data-editor-auto-created");
        if (!tab.hasAttribute("data-editor-refresh")) tab.setAttribute("data-editor-refresh", true);
        if (!tab.hasAttribute("data-editor-unsaved")) tab.setAttribute("data-editor-unsaved", true);
        refreshPreview();
    });
    preview_menu.main.appendChild(previewOption);
    applyEditingBehavior({ element: container });
    if (open || !Editor.active_editor) openEditor({ identifier, auto_created, focused_override });
    container.syntaxLanguage = Editor.query(identifier).getName("extension");
    if ((Editor.settings.get("syntax-highlighting") == true) && (container.syntaxLanguage in Prism.languages)) container.syntaxHighlight.enable();
    window.setTimeout(() => {
        if (document.body.getAttribute("data-editor-change") == changeIdentifier) document.body.removeAttribute("data-editor-change");
    }, transitionDuration);
    return identifier;
}
function openEditor({ identifier, auto_created = false, focused_override = false } = {}) {
    if (!identifier) return;
    var { tab, container, textarea, getName } = Editor.query(identifier), focused = (document.activeElement == Editor.query().container) || focused_override;
    if (Editor.query().tab) Editor.query().tab.classList.remove("active");
    if (Editor.query().container) Editor.query().container.classList.remove("active");
    tab.classList.add("active");
    if (auto_created) tab.setAttribute("data-editor-auto-created", true);
    container.classList.add("active");
    Editor.active_editor = identifier;
    setEditorTabsVisibility();
    setTitle({ content: getName() });
    if ((((document.activeElement == document.body && !Editor.active_dialog) || auto_created) && !Editor.environment().touch_device && Editor.appearance().parent_window) || focused) container.focus({ preventScroll: true });
    if (Editor.preview_editor == "active-editor") refreshPreview({ force: (Editor.settings.get("automatic-refresh") != false) });
}
function closeEditor({ identifier = Editor.active_editor } = {}) {
    if (!identifier) return;
    var { tab, container, textarea, getName } = Editor.query(identifier), previewOption = preview_menu.main.querySelector(`.option[data-editor-identifier="${identifier}"]`), active = (tab.classList.contains("active")), focused = (document.activeElement == container), editorTabs = Array.from(workspace_tabs.querySelectorAll(".tab:not([data-editor-change])"));
    if (tab.hasAttribute("data-editor-unsaved")) {
        if (!confirm(`Are you sure you would like to close "${getName()}"?\nRecent changes have not yet been saved.`)) return;
    }
    var changeIdentifier = Math.random().toString();
    if (editorTabs.length != 1) {
        document.body.setAttribute("data-editor-change", changeIdentifier);
        tab.style.setProperty("--tab-margin-right", `-${tab.offsetWidth}px`);
    } else if (document.body.hasAttribute("data-editor-change")) {
        document.body.removeAttribute("data-editor-change", changeIdentifier);
        workspace_tabs.querySelectorAll(".tab[data-editor-change]").forEach(tab => workspace_tabs.removeChild(tab));
    }
    var transitionDuration = (document.body.hasAttribute("data-editor-change")) ? parseInt(getElementStyle({ element: workspace_tabs, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000) : 0;
    if (tab == editorTabs[0] && editorTabs.length == 1) {
        Editor.active_editor = null;
        setTitle({ reset: true });
        preview.src = "about:blank";
    }
    if (Editor.preview_editor == identifier) setPreviewSource({ active_editor: true });
    if (tab == editorTabs[0] && editorTabs[1] && tab.classList.contains("active")) openEditor({ identifier: editorTabs[1].getAttribute("data-editor-identifier") });
    if (tab == editorTabs[editorTabs.length - 1] && tab != editorTabs[0] && tab.classList.contains("active")) openEditor({ identifier: editorTabs[editorTabs.length - 2].getAttribute("data-editor-identifier") });
    if (tab != editorTabs[0] && tab.classList.contains("active")) openEditor({ identifier: editorTabs[editorTabs.indexOf(tab) + 1].getAttribute("data-editor-identifier") });
    if (focused && Editor.query().textarea) Editor.query().container.focus({ preventScroll: true });
    tab.setAttribute("data-editor-change", true);
    if (tab == document.activeElement) tab.blur();
    tab.tabIndex = -1;
    if (tab.classList.contains("active")) tab.classList.remove("active");
    workspace_editors.removeChild(container);
    preview_menu.main.removeChild(previewOption);
    (transitionDuration) ? window.setTimeout(removeEditorTab, transitionDuration) : removeEditorTab();
    if (Editor.file_handles[identifier]) delete Editor.file_handles[identifier];
    function removeEditorTab() {
        if (workspace_tabs.contains(tab)) workspace_tabs.removeChild(tab);
        if (document.body.getAttribute("data-editor-change") == changeIdentifier) document.body.removeAttribute("data-editor-change");
    }
}
function renameEditor({ name, identifier = Editor.active_editor } = {}) {
    var { tab, container, getName } = Editor.query(identifier), editorName = tab.querySelector("[data-editor-name]"), previewOption = preview_menu.main.querySelector(`.option[data-editor-identifier="${identifier}"]`), currentName = getName(), base = getName("base"), extension = getName("extension"), rename = (name) ? name : prompt(`Enter a new file name for "${currentName}".`, currentName);
    if (!rename) return;
    if (!rename.includes(".")) {
        rename = `${rename}.${extension}`;
    } else if (rename.charAt(0) == ".") rename = `${base}${rename}`;
    editorName.innerText = rename;
    previewOption.innerText = rename;
    var syntaxLanguage = Editor.query(identifier).getName("extension");
    if (syntaxLanguage in Prism.languages) container.syntaxLanguage = syntaxLanguage;
    ((Editor.settings.get("syntax-highlighting") == true) && (syntaxLanguage in Prism.languages)) ? container.syntaxHighlight.enable() : container.syntaxHighlight.disable();
    if (syntaxLanguage != container.syntaxLanguage) container.syntaxLanguage = syntaxLanguage;
    if (tab.hasAttribute("data-editor-auto-created")) tab.removeAttribute("data-editor-auto-created");
    if (tab == Editor.query().tab) setTitle({ content: rename });
    if ((Editor.preview_editor == "active-editor" && Editor.active_editor == identifier) || Editor.preview_editor == identifier) refreshPreview({ force: true });
    return rename;
}
/* Future feature: Add support to disable the wrapping behavior */
function getPreviousEditor({ identifier = Editor.active_editor, wrap = true } = {}) {
    var { tab } = Editor.query(identifier), editorTabs = Array.from(workspace_tabs.querySelectorAll(".tab:not([data-editor-change])")), previousTab = editorTabs[(editorTabs.indexOf(tab) || editorTabs.length) - 1], previousEditor = previousTab.getAttribute("data-editor-identifier");
    return previousEditor;
}
function getNextEditor({ identifier = Editor.active_editor, wrap = true } = {}) {
    var { tab } = Editor.query(identifier), editorTabs = Array.from(workspace_tabs.querySelectorAll(".tab:not([data-editor-change])")), nextTab = editorTabs[(editorTabs.indexOf(tab) != editorTabs.length - 1) ? editorTabs.indexOf(tab) + 1 : 0], nextEditor = nextTab.getAttribute("data-editor-identifier");
    return nextEditor;
}
function setEditorTabsVisibility({ identifier = Editor.active_editor } = {}) {
    if (!Editor.active_editor) return;
    var { tab } = Editor.query(identifier), obstructedLeft = (tab.offsetLeft <= workspace_tabs.scrollLeft), obstructedRight = ((tab.offsetLeft + tab.clientWidth) >= (workspace_tabs.scrollLeft + workspace_tabs.clientWidth)), spacingOffset = 0;
    if ((workspace_tabs.clientWidth < tab.clientWidth) && !obstructedLeft) return;
    if (obstructedLeft) {
        spacingOffset = parseInt(getElementStyle({ element: workspace_tabs, pseudo: "::before", property: "width" }), 10) * 3;
        workspace_tabs.scrollTo(tab.offsetLeft - spacingOffset, 0);
    } else if (obstructedRight) {
        spacingOffset = parseInt(getElementStyle({ element: workspace_tabs, pseudo: "::after", property: "width" }), 10) * 3;
        workspace_tabs.scrollTo(tab.offsetLeft + tab.clientWidth + spacingOffset - workspace_tabs.clientWidth, 0);
    }
}
function setView({ type, force = false } = {}) {
    if ((Editor.orientation_change() && !force) || Editor.scaling_change()) return;
    var changeIdentifier = Math.random().toString();
    document.body.setAttribute("data-view-change", changeIdentifier);
    var transitionDuration = parseInt(getElementStyle({ element: workspace, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000);
    document.body.classList.remove(Editor.view());
    document.body.setAttribute("data-view", type);
    document.body.classList.add(Editor.view());
    removeScaling();
    view_menu.select(Editor.view());
    if (type != "preview") window.setTimeout(setEditorTabsVisibility, transitionDuration);
    window.setTimeout(() => {
        if (document.body.getAttribute("data-view-change") == changeIdentifier) document.body.removeAttribute("data-view-change");
    }, transitionDuration);
    refreshPreview();
}
function setOrientation(orientation) {
    if (Editor.orientation_change() || Editor.scaling_change()) return;
    document.body.setAttribute("data-orientation-change", true);
    var param = (orientation), transitionDuration = ((Editor.view() != "split") ? 0 : parseInt(getElementStyle({ element: workspace, property: "transition-duration" }).split(",")[0].replace(/s/g, "") * 1000));
    if (!param && Editor.view() == "split") setView({ type: "code", force: true });
    if (!param && Editor.orientation() == "horizontal") orientation = "vertical";
    if (!param && Editor.orientation() == "vertical") orientation = "horizontal";
    window.setTimeout(() => {
        setTransitionDurations("off");
        document.body.classList.remove(Editor.orientation());
        document.body.setAttribute("data-orientation", orientation);
        document.body.classList.add(Editor.orientation());
        workspace.offsetHeight;
        scaler.offsetHeight;
        preview.offsetHeight;
        setTransitionDurations("on");
        if (!param) setView({ type: "split", force: true });
        window.setTimeout(() => document.body.removeAttribute("data-orientation-change"), transitionDuration);
    }, transitionDuration);
    function setTransitionDurations(state) {
        if (state == "on") {
            workspace.style.removeProperty("transition-duration");
            scaler.style.removeProperty("transition-duration");
            preview.style.removeProperty("transition-duration");
        }
        if (state == "off") {
            workspace.style.transitionDuration = "0s";
            scaler.style.transitionDuration = "0s";
            preview.style.transitionDuration = "0s";
        }
    }
}
function setPreviewSource({ identifier, active_editor }) {
    if (!identifier && !active_editor) return;
    if ((!identifier && active_editor) || (Editor.preview_editor == identifier)) {
        Editor.preview_editor = "active-editor";
        preview_menu.select("active-editor");
    } else Editor.preview_editor = identifier;
    refreshPreview({ force: true });
}
function setSyntaxHighlighting(state) {
    state = (state != undefined) ? state : (Editor.settings.get("syntax-highlighting") != undefined);
    document.querySelectorAll("num-text").forEach(editor => {
        if (editor.syntaxLanguage in Prism.languages) (state) ? editor.syntaxHighlight.enable() : editor.syntaxHighlight.disable();
    });
    Editor.settings.set("syntax-highlighting", state);
}
function createWindow() {
    var features = (Editor.appearance().standalone || Editor.appearance().fullscreen) ? "popup" : "", win = window.open(window.location.href, "_blank", features);
    if (Editor.appearance().fullscreen) {
        win.resizeTo(window.screen.width * 2 / 3, window.screen.height * 2 / 3);
        win.moveTo(window.screen.width / 6, window.screen.height / 6);
    } else if (Editor.appearance().standalone) {
        win.resizeTo(window.outerWidth, window.outerHeight);
        win.moveTo(window.screenX, window.screenY);
    }
}
async function openFiles() {
    if (!Editor.support().file_system) {
        var input = document.createElement("input");
        input.type = "file";
        input.multiple = true;
        input.addEventListener("change", () => Array.from(input.files).forEach(file => {
            var reader = new FileReader();
            reader.readAsText(file, "UTF-8");
            reader.addEventListener("loadend", () => createEditor({ name: file.name, value: reader.result }));
        }));
        input.click();
    } else {
        var handles = await window.showOpenFilePicker({ multiple: true }).catch(error => {
            if (error.message.toLowerCase().includes("abort")) return;
        });
        if (!handles) return;
        handles.forEach(async handle => {
            var file = await handle.getFile(), identifier = createEditor({ name: await file.name, value: await file.text() });
            Editor.file_handles[identifier] = await handle;
        });
    }
}
// var id = _req('id');
// if (id) {
//     __get('txt/editBefore?id=' + id, res => {
//         if (res.code == 0) {
//             //navigator.serviceWorker.controller.postMessage({ action: "clear-site-caches" });
//             renameEditor({ name: res.data.title });
//             Editor.query().textarea.value = res.data.content;
//         }
//     })
// }
window.addEventListener('load', () => {
    window.parent.postMessage({ type: 'initSuccess' }, '*')
    window.addEventListener('message', eventHandler)
})
window.addEventListener('unload', () => {
    window.removeEventListener('message', eventHandler)
})
const base64ToBlob = (code) => {
    const parts = code.split(";base64,");
    const contentType = parts[0].split(":")[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;

    const uInt8Array = new Uint8Array(rawLength);

    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], {
        "type": contentType
    });
};
const blobToText = (blob) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (e) => {
            resolve(e.target.result);
        };
        reader.onerror = () => {
            reject();
        };
        reader.readAsText(blob);
    });
};
function isBase64(str) {
    if (str === '' || str.trim() === '') {
        return false;
    }
    try {
        return btoa(atob(str)) == str;
    } catch (err) {
        return false;
    }
}
function decodeBase64(base64String) {
    // 将Base64字符串分成每64个字符一组
    const padding = (base64String.length % 4) === 0 ? 0 : 4 - (base64String.length % 4);
    base64String += '='.repeat(padding);

    // 使用atob()函数解码Base64字符串
    const binaryString = atob(base64String);

    // 将二进制字符串转换为TypedArray
    const bytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }

    // 将TypedArray转换为字符串
    return new TextDecoder('utf-8').decode(bytes);
}
const eventHandler = (e) => {
    const eventData = e.data
    //console.log(eventData)
    if (eventData.type === 'start') {
        renameEditor({ name: eventData.title });
    }
    if (eventData.type === 'init') {
        //console.log(eventData)
        //const data = JSON.parse(eventData.data)
        const data = eventData.data
        if (!data || !data.title) {
            return;
        }
        //console.log(data)
        if(data.ext && data.ext != 'txt') {
            //Editor.query().setName("extension", data.ext);
            data.title = data.title + "." + data.ext;
        }
        //console.log(data.title)
        renameEditor({ name: data.title });
        //console.log(data)
        if (data.content) {
            if(isBase64(data.content)){
                //console.log(data.content)
                data.content = decodeBase64(data.content);
            }
            Editor.query().textarea.value = data.content;
        }
        else if (data.base64) {
            let blob = base64ToBlob(data.base64);
            blobToText(blob).then(res => {
                Editor.query().textarea.value = res;
            })
        }

    }
}
function saveData(extension) {
    let ext = Editor.query().getName("extension"),
        title = Editor.query().getName("base"),
        //title = Editor.query().getName(),
        content = Editor.query().textarea.value;
    //console.log(content)
    const save = {
        data: JSON.stringify({ content, title, ext }),
        type: 'exportText'
    }
    window.parent.postMessage(save, '*')

    // if (!id) {
    //     __post('txt/add', { title, content }, res => {
    //         if (res.code == 0) {
    //             id = res.data;
    //             _msg('保存成功')
    //         }
    //     })
    // } else {
    //     __post('txt/edit', { id, title, content }, res => {
    //         if (res.code == 0) {
    //             _msg('编辑成功')
    //         }
    //     })
    // }
}
document.getElementById('saveData').addEventListener('click', saveData)

/**
 * 保存文件
 * @param {string} extension 文件扩展名
 */
async function saveFile(extension) {
    saveData(extension);

    if (extension || !Editor.support().file_system) {
        // 如果没有指定扩展名或者不支持文件系统
        if (!extension) {
            // 获取文件扩展名
            extension = Editor.query().getName("extension");
        } else {
            // 创建一个a标签并设置下载链接
            var anchor = document.createElement("a"), link = window.URL.createObjectURL(new Blob([Editor.query().textarea.value]));
            anchor.href = link;
            anchor.download = `${Editor.query().getName("base")}.${extension}`;
            anchor.click();
            window.URL.revokeObjectURL(link);
        }
    } else {
        // 如果支持文件系统
        var identifier = Editor.active_editor, handle;
        if (!Editor.file_handles[identifier]) {
            // 显示保存文件选择器
            handle = await window.showSaveFilePicker({ suggestedName: Editor.query().getName(), startIn: (Editor.file_handles[identifier]) ? Editor.file_handles[identifier] : "desktop" }).catch(error => {
                if (error.message.toLowerCase().includes("abort")) return;
            });
            if (!handle) return;
            Editor.file_handles[identifier] = await handle;
        } else handle = Editor.file_handles[identifier];
        var stream = await Editor.file_handles[identifier].createWritable().catch(error => {
            alert(`"${Editor.query().getName()}" 保存失败`);
            if (error.toString().toLowerCase().includes("not allowed")) return;
        });
        if (!stream) return;
        await stream.write(Editor.query().textarea.value);
        await stream.close();
        var currentName = Editor.query().getName(), file = await handle.getFile(), rename = await file.name;
        if (currentName != rename) renameEditor({ name: rename });
    }

    if (Editor.query().tab.hasAttribute("data-editor-auto-created")) Editor.query().tab.removeAttribute("data-editor-auto-created");
    if (Editor.query().tab.hasAttribute("data-editor-unsaved")) Editor.query().tab.removeAttribute("data-editor-unsaved");
    refreshPreview({ force: true });
}
function createDisplay() {
    var width = window.screen.availWidth * 2 / 3,
        height = window.screen.availHeight * 2 / 3,
        left = window.screen.availWidth / 2 + window.screen.availLeft - width / 2,
        top = window.screen.availHeight / 2 + window.screen.availTop - height / 2,
        features = (Editor.appearance().standalone || Editor.appearance().fullscreen) ? "popup" : "",
        link = window.URL.createObjectURL(new Blob([Editor.query().textarea.value], { type: "text/html" })),
        win = window.open(link, "_blank", features);
    window.URL.revokeObjectURL(link);
    win.moveTo(left, top);
    win.resizeTo(width, height);
    Editor.child_windows.push(win);
    window.setTimeout(() => {
        if (!win.document.title) win.document.title = Editor.query().getName();
    }, 20);
}
async function callCommand(element, action) {/* I think I may remove this, or do something else with it. document.execCommand() is broken in so many ways, what a shame */
    element.focus({ preventScroll: true });
    if (action == "paste") {
        var clipboard = await navigator.clipboard.readText().catch(error => alert("Could not access the clipboard, please check site permissions for clipboard use."));
        document.execCommand("insertText", false, await clipboard);
    } else document.execCommand(action);
}
function getNavigableElements({ container, scope = false } = {}) {
    scope = (scope) ? "" : ":scope > ";
    var navigable = container.querySelectorAll(`${scope}button:not([disabled]), ${scope}textarea:not([disabled]), ${scope}input:not([disabled]), ${scope}select:not([disabled]), ${scope}a[href]:not([disabled]), ${scope}[tabindex]:not([tabindex="-1"])`);
    return Array.from(navigable).filter(element => (getElementStyle({ element, property: "display" }) != "none"));
}
function getElementStyle({ element, pseudo = null, property } = {}) {
    return window.getComputedStyle(element, pseudo).getPropertyValue(property);
}
function applyEditingBehavior({ element, advanced = true } = {}) {
    var type = element.tagName.toLowerCase();
    element.addEventListener("dragover", event => {
        event.stopPropagation();
        event.dataTransfer.dropEffect = "copy";
    });
    element.addEventListener("drop", event => {
        if (Array.from(event.dataTransfer.items)[0].kind == "file") return;
        event.stopPropagation();
        document.querySelectorAll("menu-drop[data-open]").forEach(menu => menu.close());
    });
    if (type == "input") {
        element.spellcheck = false;
        element.autocomplete = "off";
        element.autocapitalize = "none";
        element.setAttribute("autocorrect", "off");
    }
    if (type == "num-text") {
        element.colorScheme.set("dark");
        element.themes.remove("vanilla-appearance");
        var scrollbarStyles = document.createElement("style");
        scrollbarStyles.textContent = scrollbar_styles.textContent;
        element.shadowRoot.insertBefore(scrollbarStyles, element.container);
    }
}
function sendShortcutAction({ control, command, shift, controlShift, shiftCommand, controlCommand, key } = {}) {
    if (!key) return;
    var appleDevice = (Editor.environment().apple_device);
    control = ((control && !appleDevice) || (controlShift && !appleDevice) || (controlCommand && appleDevice)), command = ((command && appleDevice) || (shiftCommand && appleDevice) || (controlCommand && appleDevice)), shift = (shift || (controlShift && !appleDevice) || (shiftCommand && appleDevice)), key = key.toString().toLowerCase();
    document.body.dispatchEvent(new KeyboardEvent("keydown", { ctrlKey: control, metaKey: command, shiftKey: shift, key }));
}
function refreshPreview({ force = false } = {}) {
    if (Editor.view() == "code") return;
    var editor = (Editor.preview_editor == "active-editor") ? Editor.query() : Editor.query(Editor.preview_editor);
    if (!editor.textarea) return;
    var change = (editor.tab.hasAttribute("data-editor-refresh") && Editor.settings.get("automatic-refresh") != false);
    if (!change && !force) return;
    var baseURL = Editor.settings.get("preview-base") || null, source = editor.textarea.value;
    if (baseURL) {
        var sourceDOM = new DOMParser().parseFromString(source, "text/html"), baseElement = document.createElement("base");
        sourceDOM.head.prepend(baseElement);
        baseElement.href = baseURL;
        source = new XMLSerializer().serializeToString(sourceDOM);
    }
    preview.addEventListener("load", () => {
        preview.contentWindow.document.open();
        preview.contentWindow.document.write(source);
        preview.contentWindow.document.close();
    }, { once: true });
    preview.src = "about:blank";
    if (change) editor.tab.removeAttribute("data-editor-refresh");
}
function setTitle({ content, reset = false } = {}) {
    document.title = `${(content && !reset) ? `${content} - ` : ""}文本编辑器`;
}
function addQueryParameters(entries) {
    var parameters = new URLSearchParams(window.location.search);
    entries.forEach(entry => parameters.set(entry, true));
    changeQueryParameters(parameters);
}
function removeQueryParameters(entries) {
    var parameters = new URLSearchParams(window.location.search);
    entries.forEach(entry => parameters.delete(entry));
    changeQueryParameters(parameters);
}
function changeQueryParameters(parameters) {
    var query = parameters.toString();
    if (query) query = "?" + query;
    var address = window.location.pathname + query;
    history.pushState(null, "", address);
}
function showInstallPrompt() {
    Editor.install_prompt.prompt();
    Editor.install_prompt.userChoice.then(result => {
        if (result.outcome != "accepted") return;
        document.documentElement.classList.remove("install-prompt-available");
        theme_button.childNodes[0].textContent = "Customize Theme";
    });
}
function clearSiteCaches() {
    if (confirm("你要清除所有缓存吗?\n在Internet连接可用之前，文本编辑器将不再脱机工作。 ")) navigator.serviceWorker.controller.postMessage({ action: "clear-site-caches" });
}
function setScaling(event) {
    var { safe_area_insets: safeAreaInsets } = Editor.appearance(), scalingOffset, scalingRange = { minimum: ((Editor.orientation() == "vertical") ? workspace_tabs.offsetHeight : safeAreaInsets.left) + 80, maximum: ((Editor.orientation() == "horizontal") ? window.innerWidth - safeAreaInsets.right : (Editor.orientation() == "vertical") ? (window.innerHeight - header.offsetHeight - safeAreaInsets.bottom) : 0) - 80 }, touchEvent = (Editor.environment().touch_device && event instanceof TouchEvent);
    if (Editor.orientation() == "horizontal") scalingOffset = (!touchEvent) ? event.pageX : event.touches[0].pageX;
    if (Editor.orientation() == "vertical") scalingOffset = (!touchEvent) ? event.pageY - header.offsetHeight : event.touches[0].pageY - header.offsetHeight;
    if (scalingOffset < scalingRange.minimum) scalingOffset = scalingRange.minimum;
    if (scalingOffset > scalingRange.maximum) scalingOffset = scalingRange.maximum;
    document.body.setAttribute("data-scaling-active", true);
    workspace.style.setProperty("--scaling-offset", `${scalingOffset}px`);
    scaler.style.setProperty("--scaling-offset", `${scalingOffset}px`);
    preview.style.setProperty("--scaling-offset", `${scalingOffset}px`);
}
function disableScaling(event) {
    var touchEvent = (Editor.environment().touch_device && event instanceof TouchEvent);
    document.removeEventListener((!touchEvent) ? "mousemove" : "touchmove", setScaling);
    document.removeEventListener((!touchEvent) ? "mouseup" : "touchend", disableScaling);
    document.body.removeAttribute("data-scaling-change");
}
function removeScaling() {
    if (!document.body.hasAttribute("data-scaling-active")) return;
    document.body.removeAttribute("data-scaling-active");
    workspace.style.removeProperty("--scaling-offset");
    scaler.style.removeProperty("--scaling-offset");
    preview.style.removeProperty("--scaling-offset");
}